package com.jpo.common.utils;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 公共工具类
 * 日期
 * MD5加密
 * 邮箱格式校验
 */
@Slf4j
public class CommonUtil {

    // MD5加密盐
    public static final String SALT = "qwer!#@4845";

    /**
     * 获取当前日期
     *
     * @return 格式：yyyy-MM-dd HH:mm:ss
     */
    public static String getCurrTime() {
        return format(new Date(), "");
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date getNowTime() {
        return new Date();
    }

    /**
     * 将字符串转换为Date类型
     *
     * @param date 字符串类型
     * @return 日期类型
     */
    public static Date format(String date) {
        return format(date, null);
    }

    /**
     * 将Date类型转换为字符串
     *
     * @param date    日期类型
     * @param pattern 字符串格式
     * @return 日期字符串
     */
    public static String format(Date date, String pattern) {
        if (date == null) {
            return "null";
        }
        if (pattern == null || pattern.equals("") || pattern.equals("null")) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 将Date类型转换为字符串
     *
     * @param date    日期类型
     * @param pattern 字符串格式
     * @return 日期字符串
     */
    public static String format(Object date, String pattern) {
        if (date == null) {
            return "null";
        }
        if (pattern == null || pattern.equals("") || pattern.equals("null")) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 将Date类型转换为字符串
     *
     * @param date 日期类型
     * @return 日期字符串
     */
    public static String format(Date date) {
        if (date == null) {
            return "null";
        }

        return new SimpleDateFormat("yyyy年MM月dd日").format(date);
    }

    /**
     * 将字符串转换为Date类型
     *
     * @param date    字符串类型
     * @param pattern 格式
     * @return 日期类型
     */
    public static Date format(String date, String pattern) {
        if (pattern == null || pattern.equals("") || pattern.equals("null")) {
            pattern = "yyyy-MM-dd HH:mm:ss";
        }
        if (date == null || date.equals("") || date.equals("null")) {
            pattern = "mm:ss";
        }
        Date d = null;
        try {
            d = new SimpleDateFormat(pattern).parse(date);
        } catch (ParseException pe) {
            pe.printStackTrace();
        }
        return d;
    }

    /**
     * 判断是否为邮箱
     *
     * @param string 字符串
     * @return
     */
    public static boolean isEmail(String string) {
        if (string == null)
            return false;
        String regEx1 = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
        Pattern p = Pattern.compile(regEx1);
        Matcher m = p.matcher(string);
        return m.matches();
    }

    /**
     * 对象转map
     * 显示值为null的字段
     * 将为null的字段值显示为""
     *
     * @param obj
     * @return
     */
    public static Map<String, Object> objectToMap(Object obj) {
        String jsonString = JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty);
        Map<String, Object> stringObjectMap = JSON.parseObject(jsonString, new TypeReference<Map<String, Object>>() {
        });
        return stringObjectMap;
    }

    /**
     * MD5加密
     *
     * @param s
     * @return
     */
    public final static String MD5(String s) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            s = s + SALT;
            byte[] btInput = s.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * int相除获取百分数
     *
     * @param num1
     * @param num2
     * @return
     */
    public static String formatRate(int num1, int num2) {
        if (num2 == 0)
            return "0";
        float num = (float) num1 * 100 / num2;
        DecimalFormat decimalFormat = new DecimalFormat("0.00");
        String format = decimalFormat.format(num);
        return format;
    }

    /**
     * 由过去的某一时间,计算距离当前的时间
     *
     * @param time
     * @return
     */
    public static String calculateTime(String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//指定时间格式
        Date setTime = null;  //指定时间
        try {
            setTime = sdf.parse(time);  //将字符串转换为指定的时间格式
        } catch (ParseException e) {

            e.printStackTrace();
        }
        return calculateTime(setTime);
    }


    /**
     * 由过去的某一时间,计算距离当前的时间
     */
    public static String calculateTime(Date time) {
        long nowTime = System.currentTimeMillis();  //获取当前时间的毫秒数
        String msg = null;

        long reset = time.getTime();   //获取指定时间的毫秒数
        long dateDiff = nowTime - reset;

        if (dateDiff < 0) {
            msg = "";
        } else {

            long dateTemp1 = dateDiff / 1000; //秒
            long dateTemp2 = dateTemp1 / 60; //分钟
            long dateTemp3 = dateTemp2 / 60; //小时
            long dateTemp4 = dateTemp3 / 24; //天数
            long dateTemp5 = dateTemp4 / 30; //月数
            long dateTemp6 = dateTemp5 / 12; //年数

            if (dateTemp6 > 0) {
                msg = dateTemp6 + "年前";

            } else if (dateTemp5 > 0) {
                msg = dateTemp5 + "个月前";

            } else if (dateTemp4 > 0) {
                msg = dateTemp4 + "天前";

            } else if (dateTemp3 > 0) {
                msg = dateTemp3 + "小时前";

            } else if (dateTemp2 > 0) {
                msg = dateTemp2 + "分钟前";

            } else if (dateTemp1 > 0) {
                msg = "刚刚";

            }
        }
        return msg;

    }

    /**
     * 计算两个日期相差的天数
     *
     * @param startDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    public static int getDayDiffer(Date startDate, Date endDate) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        long startDateTime = dateFormat.parse(dateFormat.format(startDate)).getTime();
        long endDateTime = dateFormat.parse(dateFormat.format(endDate)).getTime();
        return (int) ((endDateTime - startDateTime) / (1000 * 3600 * 24));
    }

    /**
     * 将路径替换为相对路径
     *
     * @param rootPath 根路径
     * @param path     要替换的路径
     * @return
     */
    public static String getRelativePath(String rootPath, String path) {
        try {
            if (!StringUtils.isEmpty(rootPath) && !StringUtils.isEmpty(path)) {
                // 替换 root.path 形式和 server.path 形式
                String newPath = path.replace(new File(rootPath).getPath(), "")
                        .replace(rootPath, "");
                //            String newPath = new File(rootPath, path.split(rootPath)[1]).getPath();
                return newPath;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return path;
    }

    /***
     * @Description: 比较date3是否在date1与date2之间，只按日期比较，不算时间
     * @Param: [date1, date2, date3]
     * @return:
     * @Author: chenqq
     * @Date: 2021/11/6
     */
    public static boolean betweenDate(Date date1, Date date2, Date date3) {
        if (date2.before(date1))
            return false;

        int res1 = differDayQty(date1, date3);
        int res2 = differDayQty(date2, date3);
        return (res1 >= 0 && res2 <= 0);
    }

    /**
     * 比较两个日期Date2比Date1(年月日)多的天数,(只考虑天数不考虑时间)
     * 例如:2017-01-25 23:59:59与 2017-01-26 00:00:00   返回1
     * 2017-01-25 与 2017-01-25   返回0
     * 2017-01-28 与 2017-01-25   返回-3
     */
    public static int differDayQty(Date date1, Date date2) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.setTime(date1);
        int day1 = calendar.get(Calendar.DAY_OF_YEAR);
        int year1 = calendar.get(Calendar.YEAR);
        calendar.setTime(date2);
        int day2 = calendar.get(Calendar.DAY_OF_YEAR);
        int year2 = calendar.get(Calendar.YEAR);
        if (year1 == year2) {//同一年
            return day2 - day1;
        } else if (year1 < year2) {//Date1<Date2
            int days = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {//闰年
                    days += 366;
                } else {
                    days += 365;
                }
            }
            return days + (day2 - day1);
        } else {//Date1>Date2
            int days = 0;
            for (int i = year2; i < year1; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                    days += 366;
                } else {
                    days += 365;
                }
            }
            return 0 - days + (day2 - day1);
        }
    }

    /**
     * 内容编码
     *
     * @param str 内容
     * @return 编码后的内容
     */
    public static String urlEncode(String str) {
        try {
            return URLEncoder.encode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }

    /**
     * 内容解码
     *
     * @param str 内容
     * @return 解码后的内容
     */
    public static String urlDecode(String str) {
        try {
            return URLDecoder.decode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return "";
        }
    }

    /**
     * 拼接访问图片路径
     *
     * @return
     */
    public static String getServerPath(String serverPath, String path) {
        try {
//            if (StringUtils.isNotBlank(path) && path.contains("/")) {
                path = serverPath + path;
                return path;
//            }
//            return path;
        } catch (Exception e) {
            log.error("CommonUtil.handleUserHeadPath", e);
            return path;
        }
    }

    /**
     * 通过userInfo获取用户名称
     *
     * @param userInfo
     * @return
     */
    public static String getUserName(String userInfo) {
        try {
            if (StringUtils.isBlank(userInfo))
                return "";
            if (userInfo.contains("|"))
                return userInfo.split("\\|")[0];
        } catch (Exception e) {
            log.error("CommonUtil.getUserName", e);
            return userInfo;
        }
        return userInfo;
    }

    public static List<String> getDateList(Date startDate, Date endDate) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd");
        List<String> listDate = new ArrayList<>();
        try {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startDate);
            while (calendar.getTime().before(endDate) || calendar.getTime().equals(endDate)) {
                listDate.add(dateFormat.format(calendar.getTime()));
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
            return listDate;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return listDate;
    }

    /**
    * @Description 合并List<Map>
    * @Param  m1
	* @Param  m2
    * @return java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
    * @Author chen_qq
    * @Date   2022/1/10
    */
    public static List<Map<String, Object>> merge(List<Map<String, Object>> m1, List<Map<String, Object>> m2) {
        if (CollectionUtil.isEmpty(m1) || CollectionUtil.isEmpty(m2))
            return null;

        try {
            m1.addAll(m2);

            Set<String> set = new HashSet<>();

            return m1.stream()
                    .collect(Collectors.groupingBy(o -> {
                        //暂存所有key
                        set.addAll(o.keySet());
                        //按a_id分组
                        return o.get("id");
                    })).entrySet().stream().map(o -> {

                        //合并
                        Map<String, Object> map = o.getValue().stream().flatMap(m -> {
                            return m.entrySet().stream();
                        }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> b));

                        //为没有的key赋值0
                        set.stream().forEach(k -> {
                            if (!map.containsKey(k)) {
                                map.put(k, 0);
                            }
                        });

                        return map;
                    }).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("CommonUtil.merge", e);
            return null;
        }
    }

    /**
     * 用于处理 String.valueOf后的数据判空
     * @param obj
     * @return
     */
    public static Boolean isEmpty(Object obj) {
        String str = String.valueOf(obj);
        return StringUtils.isEmpty(str) || "null".equals(str);
    }

    public static Boolean isNotEmpty(Object str) {
        return !isEmpty(str);
    }

    public static String[] splitStr(String str,String regex){
        if (StringUtils.isNotBlank(str)){
            return str.split(regex);
        }else {
            return new String[]{};
        }
    }

    /**
     * 根据当前编号获取最大编号
     * @param currMaxCode  当前最大编号
     * @param digits       格式化后位数  0,1,2,3....
     */
    public static String maxCode(String currMaxCode, String digits) {
        if (StringUtils.isEmpty(currMaxCode))
            currMaxCode = "0";
        Integer codes = Integer.valueOf(currMaxCode) + 1;
        String code = String.format("%0" + digits + "d", codes);
        return code;
    }

    /**
     * 去掉空格
     * @param name
     * @return
     */
    public static String removeSpace(String name) {
        if (StringUtils.isBlank(name))
            return "";

        name = name.trim().replaceAll(" ", "").replaceAll("\\s*", "");
        return name;
    }
}
